package controllers;

import java.io.InputStream;
import java.net.URL;
import play.*;
import play.mvc.*;

import java.util.*;

import models.*;
import play.db.jpa.Blob;

public class Circles extends Controller {

	public static Set<Circle> getGroupsOfCurrentUser() {
		User currentUser = Login.getCurrentUser();
		if (currentUser != null) {
			return currentUser.circles;
		}
		return null;
	}
	
	public static void getGroupsOfCurrentUserJSON() {
		Set<Circle> g = getGroupsOfCurrentUser();
		if (g != null) {
			renderJSON(g);
		} else {
			renderJSON(false);
		}
	}
	
	public static void getCirclesByUserId() {
		Long uid = Long.valueOf(params.get("pid"));
		User u = User.findById(uid);
		if(u == null) {
			renderJSON("{error:\"User not found.\"}");
		} else {
			Set<Circle> cs = u.circles;
			if (cs == null) {
				renderJSON("{error:\"User has no circles.\"}");
			} else {
				renderJSON(cs, new CircleSerializer());
			}
		}
	}
	
	public static void getAllCircles() {
		List<Circle> cs = Circle.findAll();
		if (cs == null) {
			renderJSON("{error:\"There is not any circles.\"}");
		} else {
			renderJSON(cs, new CircleSerializer());
		}
	}
	
	public static Set<Circle> getJoinedCirclesByUserId(User u) {
		Set<Circle> circles = u.circles;
		if (circles != null) {
			return circles;
		} else {
			return null;
		}
	}
	
	public static Set<Circle> getNotJoinedCirclesByUserId(User u) {
		List<Circle> cs = Circle.findAll();
		Set<Circle> ca = new HashSet<Circle>(cs);
		Set<Circle> cu = u.circles;
		Iterator i = cu.iterator();
		while(i.hasNext()) {
			Circle element = (Circle)i.next();
			ca.remove(element);
		}
		return ca;
	}
		
	public static void getCirclesJSON() {
		int type = Integer.valueOf(params.get("type"));
		Long pid = Long.valueOf(params.get("pid"));
		
		//System.out.println("type is "+ type + " pid is " + pid);
		
		User u = User.findById(pid);
		if(u == null) {
			renderJSON("{\"error\":\"invalid pid\"}");
		} else {
			Set<Circle> c = getCircles(u,type);
			if(c != null) {
				renderJSON(c, new CircleSerializer());
			} else {
				renderJSON("{\"error\":\"no such circles\"}");
			}
		}
	}
	
	public static Set<Circle> getCircles(User u,int type) {
		switch(type) {
			case 0:	// circles user already in
				return getJoinedCirclesByUserId(u);
			case 1:	// circles user not in yet
				return getNotJoinedCirclesByUserId(u);
			default:
				return getJoinedCirclesByUserId(u);
		}
	}
	
	public static void getMembersByCircleId() {
		Long cid = Long.valueOf(params.get("cid"));
		Circle c = Circle.findById(cid);
		if(c == null) {
			renderJSON("{\"error\":\"Circle not found.\"}");
		} else {
			Set<User> ms = c.members;
			if (ms == null) {
				renderJSON("{\"error\":\"Circle has no members.\"}");
			} else {
				renderJSON(ms, new UserSerializer());
			}
		}
	}
	
	public static void currentUserInCircle() {
		Long cid = Long.valueOf(params.get("cid"));
		Circle c = Circle.findById(cid);
		User currentUser = Login.getCurrentUser();
		if(currentUser == null) {
			renderJSON("{\"state\":\"no current user\"}");
		} else {
			if(c == null) {
				renderJSON("{\"state\":\"no circle\"}");
			} else if(currentUser.inCircle(c)) {
				renderJSON("{\"state\":\"in circle\"}");
			} else {
				renderJSON("{\"state\":\"not in circle\"}");
			}
		}
	}
	
	public static void addMember() {
		Long cid = Long.valueOf(params.get("cid"));
		User currentUser = Login.getCurrentUser();
		renderJSON(currentUser.joinCircle(cid));
	}
	
	public static void currentUserLeaveCircle(Long cid) {
		Circle c = Circle.findById(cid);
		User currentUser = Login.getCurrentUser();
		if(currentUser == null) {
			renderJSON("{\"error\":\"invalid user\"}");
		} else {
			if(c == null) {
				renderJSON("{\"error\":\"invalid cid\"}");
			} else {
				renderJSON(currentUser.leaveCircle(c));
			}
		}	
	}
	
	public static void getCircleInfo(Long cid) {
		Circle c = Circle.findById(cid);
		if(c == null) {
			renderJSON("{\"error\":\"invalid cid\"}");
		} else {
			renderJSON(c, new CircleSerializer());
		}
	}

	public static void updateCircleMap(Long cid) {
		Circle c = Circle.findById(cid);
		if(c != null) {
			InputStream is = null;
			try {
				URL url = new URL("https://maps.googleapis.com/maps/api/staticmap?center="
						+c.lat
						+","
						+c.lng
						+"&zoom=14&size=180x180&maptype=roadmap&markers=color:red%7Clabel:S%7C"
						+c.lat
						+","
						+c.lng
						+"&sensor=false");
				is = url.openConnection().getInputStream();

			} catch (Exception ex) {
				System.out.println(ex+"");
			}
			c.distroyMap();
			c.map = new Blob();
			c.map.set(is, "image/png");
			c.save();
		}
	}
	
	public static void displayCircleAvatar(Long cid) {
		Circle c = Circle.findById(cid);
		if(c!= null) {
			if(c.hasPhoto()) {
				response.setContentTypeIfNotSet(c.photo.type());
				renderBinary(c.photo.get());
			} else {
				displayCircleMap(cid);
			}
		} else {
			renderJSON("{\"error\":\"invalid cid\"}");
		}
	}
	
	public static void displayCircleMap(Long cid) {
		Circle c = Circle.findById(cid);
		if(c!= null) {
			if(!c.hasMap()) {
				updateCircleMap(c.id);
			}
			response.setContentTypeIfNotSet(c.map.type());
			renderBinary(c.map.get());
		} else {
			renderJSON("{\"error\":\"invalid cid\"}");
		}
	}
	
	public static void createCircle(String name, String addr, double lat, double lng, String tags, Long uid) {
		Circle c = new Circle(name, "", addr, lat, lng, uid);
		String[] tgs = tags.split(",");
		for(int i = 0; i < tgs.length; i++) {
			c.addTag(tgs[i]);
		}
		c.addMember(uid);
//		if(!c.hasMap()) {
//			updateCircleMap(c.id);
//		}
		renderJSON("{\"success\":\"true\",\"cid\":" + c.id + "}");
	}
	
//	public static void getTagsByCircleId(Long cid) {
//		Circle c = Circle.findById(cid);
//		if(c != null) {
//			renderJSON("{\"tags\":\"" + c.getTagsString() + "\"}");
//		} else {
//			renderJSON("{\"error\":\"invalid cid\"}");
//		}
//	}
//	
//	public static void getPostNumberByCircleId(Long cid) {
//		Circle c = Circle.findById(cid);
//		if(c != null) {
//			renderJSON("{\"numbers\":\"" + c.getPostNumber() + "\"}");
//		} else {
//			renderJSON("{\"error\":\"invalid cid\"}");
//		}
//	}
//	
//	public static void getMemberNumberByCircleId(Long cid) {
//		Circle c = Circle.findById(cid);
//		if(c != null) {
//			renderJSON("{\"numbers\":\"" + c.getMemberNumber() + "\"}");
//		} else {
//			renderJSON("{\"error\":\"invalid cid\"}");
//		}
//	}
	
	public static void getCirclesByName() {
		String cname = params.get("cname");
		Circle c = Circle.find("byName", cname).first();  //circles should have unique names
		List<Circle> cs = Circle.find("select c from Circle c where c.name like ?", "%"+cname+"%").fetch();
		Set<Circle> result = new HashSet();
		if(c != null) {
			result.add(c);
		}
		if(cs != null) {
			result.addAll(cs);
		}
		if(result != null) {
			renderJSON(result, new CircleSerializer());
		} else {
			renderJSON("{\"error\":\"invalid cname\"}");
		}
	}
	
	public static void getCircleByName() {
		String cname = params.get("cname");
		Circle c = Circle.find("byName", cname).first();
		if(c != null) {
			renderJSON(c, new CircleSerializer());
		} else {
			renderJSON("{\"error\":\"invalid cname\"}");
		}
	}
	
	public static void getRandomCircles() {
		Integer cn = Integer.valueOf(params.get("number"));
		List<Circle> cl = Circle.findAll();
		Integer tcn = cl.size();
		Set<Circle> result = new HashSet();
		for(int i=0;i<cn;i++) {
			if(cl.size() == 0) {
				break;
			}
			int index = 1 + (int)(Math.random() * (tcn - i));
			Circle c = cl.get(index-1);
			cl.remove(index-1);
			result.add(c);
		}
		if(result != null) {
			renderJSON(result, new CircleSerializer());
		} else {
			renderJSON("{\"error\":\"invalid cname\"}");
		}
	}
	
}